package com.example.emos.wx.core.config;


import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.ApiSelectorBuilder;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;


import java.util.ArrayList;
import java.util.List;

/**
 * Swagger2配置类
 *
 * @Author YinXi
 * @Versin 1.0.0
 * @Date 2023/7/25
 */
@Configuration
//开启Swagger注解
@EnableSwagger2
public class SwaggerConfig {
    /**
     * Swagger的各种配置信息最终都要封装到Docket中
     * 创建Docket
     * 最终返回给Springboot @Bean
     *
     * @return 一个Docket
     */
    @Bean
    public Docket createRestApi(){
        //创建一个Docket对象并指定文档类型
        Docket docket =new Docket(DocumentationType.SWAGGER_2);

        //设置文档的标题
        ApiInfoBuilder apiInfoBuilder = new ApiInfoBuilder();
        apiInfoBuilder.title("EMCRed在线办公系统");
        ApiInfo apiInfo = apiInfoBuilder.build();
        docket.apiInfo(apiInfo);

        //设置那些类的那些方法添加到Swagger
        ApiSelectorBuilder selectorBuilder = docket.select();
        //设置什么包中的什么类添加到Swagger中，默认情况下将所有包中的所有类添加到Swagger中
        selectorBuilder.paths(PathSelectors.any());
        //这些类里面的特定注解方法才可以添加到Swagger,也就是只有注解了ApiOperation才能添加到Swagger页面
        selectorBuilder.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class));
        //将上述的配置放到Docket中
        docket = selectorBuilder.build();

        //让Swagger支持JWT
        //客户端发起JWT请求时需要上传令牌，规定在header中接收客户端上传的令牌，在请求头中通过token参数获取客户端的令牌第二个参数是描述信息
        ApiKey apiKey = new ApiKey("token","token","header");
        //把Apikey封装到一个List中把List交给Docket
        List<ApiKey> apiKeys = new ArrayList<>();
        apiKeys.add(apiKey);
        docket.securitySchemes(apiKeys);
        //设定令牌的作用域创建认证对象
        AuthorizationScope scope = new AuthorizationScope("global","accessEverything");
        //把认证对象放置到数组当中，再次进行封装
        AuthorizationScope[] scopes = {scope};
        //使用SecurityReference再次进行封装
        SecurityReference reference = new SecurityReference("token",scopes);
        //再次将SecurityReference进行封装
        List refList = new ArrayList();
        refList.add(reference);
        //使用SecurityContext再次进行封装
        SecurityContext context = SecurityContext.builder().securityReferences(refList).build();
        //再次封装到List集合才能给Docket使用
        List cxtList = new ArrayList();
        cxtList.add(context);
        docket.securityContexts(cxtList);

        return docket;
    }
}
